import IDispatcher from "../interfaces/IDispatcher";
import ISprite from "../interfaces/ISprite";
import SpriteNode from "./SpriteNode";
import SpriteFactory from "../factorys/SpriteFactory";
import ERenderType from "../enums/ERenderType";
import ISpriteContainer from "../interfaces/ISpriteContainer";
import CanvasMouseEvent from "../events/CanvasMouseEvent";
import EInputEventType from "../enums/EInputEventType";
import CanvasKeyBoardEvent from "../events/CanvasKeyBoardEvent";
import TreeNode from "../core/TreeNode";

export default class SpriteNodeManager implements IDispatcher {
    private _rootNode: SpriteNode;
    private _dragSprite: ISprite | undefined = undefined;
    public constructor(width: number, height: number) {
        let spr: ISprite = SpriteFactory.createISprite(SpriteFactory.createGrid(width, height));
        spr.name = 'root';
        spr.strokeStyle = "black";
        spr.fillStyle = 'white';
        spr.renderType = ERenderType.STROKE_FILL;
        this._rootNode = new SpriteNode(spr, undefined, spr.name);
        spr.owner = this._rootNode;
    }

    public get container(): ISpriteContainer {
        return this._rootNode;
    }

    public dispatchMouseEvent(evt: CanvasMouseEvent): void {
        if (evt.type === EInputEventType.MOUSEUP) {
            this._dragSprite = undefined;
        } else if (evt.type === EInputEventType.MOUSEDRAG) {
            if (this._dragSprite !== undefined) {
                if (this._dragSprite.mouseEvent !== null) {
                    this._dragSprite.mouseEvent(this._dragSprite, evt);
                    return;
                }
            }
        }

        let spr: ISprite | undefined = this._rootNode.findSprite(evt.canvasPosition, evt.localPosition);
        if (spr !== undefined) {
            evt.hasLocalPosition = true;
            if (evt.button === 0 && evt.type === EInputEventType.MOUSEDOWN) {
                this._dragSprite = spr;
            }

            if (evt.type === EInputEventType.MOUSEDRAG)
                return;

            if (spr.mouseEvent) {
                spr.mouseEvent(spr, evt);
                return;
            }
        } else {
            evt.hasLocalPosition = false;
        }
    }


    public dispatchKeyEvent(evt: CanvasKeyBoardEvent): void {
        this._rootNode.visit(
            (node: TreeNode<ISprite>): void => {
                if (node.data !== undefined) {
                    if (node.data.keyEvent !== null) {
                        node.data.keyEvent(node.data, evt);
                    }
                }
            }
        );
    }

    dispatchUpdate(msec: number, diffSec: number): void {
        this._rootNode.update(msec, diffSec);
    }

    dispatchDraw(context: CanvasRenderingContext2D): void {
        this._rootNode.draw(context);
    }
}